package com.koc.robot;

import java.io.IOException;
import java.io.InputStream;

import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES11;
import android.opengl.GLUtils;

import com.koc.robot.util.GLResourceHelper;
import com.koc.robot.util.Resource;

//bitmap texture
public class Texture implements Resource {

    private Context mContext;
    
    private int mTextureID;
    private int mTextureWidth;
    private int mTextureHeight;
    
    private int mResourceID = -1;
    private String mPath = null;

    
    public Texture(Context context)
    {
    	mContext = context;
    	mTextureID = -1;
    	
    	GLResourceHelper.sharedHelper().AddGLResource(this);
    }
    
    public boolean load(int idInR)
    {
        int[] textures = new int[1];
        GLES11.glGenTextures(1, textures, 0);

        mTextureID = textures[0];
        //GLES11.glBindTexture(GLES11.GL_TEXTURE_2D, mTextureID);
        GraphicsHelper.bindTexture(mTextureID); 

        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MIN_FILTER,
                GLES11.GL_NEAREST);
        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D,
                GLES11.GL_TEXTURE_MAG_FILTER,
                GLES11.GL_LINEAR);

        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_S,
                GLES11.GL_CLAMP_TO_EDGE);
        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_T,
                GLES11.GL_CLAMP_TO_EDGE);

        GLES11.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_TEXTURE_ENV_MODE,
                GLES11.GL_MODULATE);

        boolean ret = false;
        InputStream is = mContext.getResources().openRawResource(idInR);
        Bitmap bitmap = null;
        try {
        	if(is != null)
        		bitmap = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch(IOException e) {
                // Ignore.
            	ret = false;
            }
        }

        if(bitmap != null)
        {
            GLUtils.texImage2D(GLES11.GL_TEXTURE_2D, 0, bitmap, 0);
            mTextureWidth = bitmap.getWidth();
            mTextureHeight = bitmap.getHeight();
            
            bitmap.recycle();
            
            createBuffers();
            
            ret = true;
            
            mResourceID = idInR;
        }

    	return ret;
    }
    
    public boolean load(String path)
    {
        int[] textures = new int[1];
        GLES11.glGenTextures(1, textures, 0);

        mTextureID = textures[0];
        //GLES11.glBindTexture(GLES11.GL_TEXTURE_2D, mTextureID);
        GraphicsHelper.bindTexture(mTextureID);

        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MIN_FILTER,
                GLES11.GL_NEAREST);
        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D,
                GLES11.GL_TEXTURE_MAG_FILTER,
                GLES11.GL_LINEAR);

        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_S,
                GLES11.GL_CLAMP_TO_EDGE);
        GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_T,
                GLES11.GL_CLAMP_TO_EDGE);

        GLES11.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_TEXTURE_ENV_MODE,
                GLES11.GL_MODULATE);

        boolean ret = false;  
        Bitmap bitmap = null;
        try
        {
            InputStream is = mContext.getAssets().open(path);
            if(is != null)
            	bitmap = BitmapFactory.decodeStream(is);
        }
        catch(Exception e)
        {
        	
        }
        
        if(bitmap != null)
        {
            GLUtils.texImage2D(GLES11.GL_TEXTURE_2D, 0, bitmap, 0);
            mTextureWidth = bitmap.getWidth();
            mTextureHeight = bitmap.getHeight();	
            
            bitmap.recycle();
            
            createBuffers();
            
            mPath = path;
           
            ret = true;
        }    
    	
    	return ret;
    }
    
  //  @Override
    public void reload()
    {
    	if (mResourceID != -1)
    	{
    		load(mResourceID);
    	}
    	else if (mPath != null)
    	{
    		load(mPath);
    	}
    }
    
    @Override
    protected void finalize() throws Throwable
    {
    	if (mTextureID != 0)
    	{
    		int[] textureID = new int[] {mTextureID};
    		GLES11.glDeleteTextures(1, textureID, 0);
    	}
    	
    	super.finalize();
    }
    
    public void setFilter(FilterMode minFilter, FilterMode magFilter)
    {
    	int gmin, gmag;
    	gmin = gmag = 0;
    	
    	switch (minFilter)
    	{
    	case FILTER_LINEAR:
    		gmin = GLES11.GL_LINEAR;
    		break;
    	case FILTER_NEAREST:
    		gmin = GLES11.GL_NEAREST;
    		break;
    	default:
    		break;
    	}
    	
    	switch (magFilter)
    	{
    	case FILTER_LINEAR:
    		gmag = GLES11.GL_LINEAR;
    		break;
    	case FILTER_NEAREST:
    		gmag = GLES11.GL_NEAREST;
    		break;
    	default:
    		break;
    	}
    	
    	if (mTextureID != 0)
    		GraphicsHelper.bindTexture(mTextureID);
    	
    	GLES11.glTexParameteri(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MIN_FILTER, gmin);
    	GLES11.glTexParameteri(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MAG_FILTER, gmag);
    }
    
    public int getTextureID()
    {
    	return mTextureID;
    }
    
    public int getTextureWidth()
    {
    	return mTextureWidth;
    }
    
    public int getTextureHeight()
    {
    	return mTextureHeight;
    }
    
    public FloatBuffer getVerticesBuffer()
    {
    	return mVertices;
    }
    
    public FloatBuffer getCoordinatesBuffer()
    {
    	return mCoordinates;
    }
    
    private void createBuffers()
    {
    	ByteBuffer vfb = ByteBuffer.allocateDirect(4 * 2 * 4);
    	vfb.order(ByteOrder.nativeOrder());
    	mVertices = vfb.asFloatBuffer();
    	
    	ByteBuffer tfb = ByteBuffer.allocateDirect(4 * 2 * 4);
    	tfb.order(ByteOrder.nativeOrder());
    	mCoordinates = tfb.asFloatBuffer();
    	
    	float vertices[] = {0.0f, 0.0f,
    					    mTextureWidth, 0.0f,
    					    mTextureWidth, mTextureHeight,
    					    0.0f, mTextureHeight};
    	mVertices.put(vertices);
    	mVertices.position(0);
    	
    	float coordinates[] = 
    		{
    			0.0f, 0.0f,
    			1.0f, 0.0f,
    			1.0f, 1.0f,
    			0.0f, 1.0f
    		};
    	mCoordinates.put(coordinates);
    	mCoordinates.position(0);
    }
    
    private FloatBuffer mVertices = null;
    private FloatBuffer mCoordinates = null;
}
